﻿using System;
using System.Threading;
using SLS.ExClassLib.MultiThreading.Threading.ThreadPools.Statistics;
using SLS.ExClassLib.MultiThreading.Threading.ThreadPools.TaskItems;
using SLS.ExClassLib.MultiThreading.Threading.ThreadPools.TaskQueueControllers;
using log4net;
using SLS.ExClassLib.MultiThreading.Extensions;

namespace SLS.ExClassLib.MultiThreading.Threading.ThreadPools
{
    public sealed class WorkThread : IDisposable
    {
        private readonly ILog _log;
        private readonly IStatisticController _statisticController;
        private readonly ITaskQueueController _taskQueueController;
        private volatile bool _isRun = true;

        public WorkThread(ITaskQueueController taskQueueController, IStatisticController statisticController)
        {
            if (taskQueueController.IsNull())
                throw new ArgumentNullException("taskQueueController", "taskQueueController is null");
            if (statisticController.IsNull())
                throw new ArgumentNullException("statisticController", "statisticController is null");
            _statisticController = statisticController;
            _taskQueueController = taskQueueController;
            _log = LogManager.GetLogger(GetType());
        }

        public Thread Thread { private get; set; }

        #region IDisposable Members

        public void Dispose()
        {
            Stop();
            _taskQueueController.Dispose();
            Thread.Join();
        }

        #endregion

        public void Start()
        {
            while (_isRun)
            {
                WorkItem workItem = null;
                try
                {
                    workItem = _taskQueueController.Dequeue();
                    if (workItem.IsNull())
                        continue;
                    _statisticController.WorkItemStarted();
                    DoWork(workItem);
                }
                catch (Exception ex)
                {
                    _log.Error(ex.Message);
                }
                finally
                {
                    if (workItem.IsNotNull())
                        _statisticController.WorkItemCompleted();
                }
            }
        }

        private void Stop()
        {
            _isRun = false;
        }

        private void DoWork(WorkItem workItem)
        {
            workItem.TaskItem.DoWork();
        }
    }
}